/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.core.data.extendhandler;

import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.spi.extend.datatype.ICefDataExtend;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class CefDataExtHandler implements Cloneable {

   protected List<ICefData> extendDatas;
   protected List<ICefDataExtend> extendList;

   public void addExtend(ICefDataExtend ext) {
      Objects.requireNonNull(ext, "ext");

      ICefData extendData = createData(ext);

      //TODO: 检查extData.PropertyNames与当前PropertyNames是否重复

      onAddingExtend(ext, extendData);

      if (extendDatas == null) {
         extendDatas = new ArrayList<>();
      }
      extendDatas.add(extendData);

      if (extendList == null) {
         extendList = new ArrayList<>();
      }
      extendList.add(ext);
   }

   public List<ICefDataExtend> getExtendList() {
      if (extendList == null) {
         return Collections.emptyList();
      }
      return Collections.unmodifiableList(extendList);
   }

   protected ICefData createData(ICefDataExtend ext) {
      return ext.createData();
   }

   protected void onAddingExtend(ICefDataExtend ext, ICefData extendData) {
   }

   public boolean getValue(String s, RefObject<Object> result) {
      if (extendDatas == null) {
         return false;
      }
      for (ICefData data : extendDatas) {
         if (data.getPropertyNames().contains(s)) {
            result.argvalue = data.getValue(s);
            return true;
         }
      }
      return false;
   }

   public boolean createValue(String propertyName, RefObject<Object> result) {
      if (extendList == null) {
         return false;
      }
      for (ICefDataExtend extender : extendList) {
         if (extender.createValue(propertyName, result)) {
            return true;
         }
      }
      return false;
   }

   public boolean setValue(String name, Object value) {
      if (extendDatas == null) {
         return false;
      }
      for (ICefData data : extendDatas) {
         if (data.getPropertyNames().contains(name)) {
            data.setValue(name, value);
            return true;
         }
      }
      return false;
   }

   public List<String> getPropertyNames() {
      if (extendDatas == null) {
         return Collections.emptyList();
      }
      List<String> result = new ArrayList<>();
      for (ICefData data : extendDatas) {
         result.addAll(data.getPropertyNames());
      }
      return result;
   }

   protected final List<ICefData> getExtendDatas() {
      return extendDatas;
   }

   public void clear() {
      if (extendDatas != null && !extendDatas.isEmpty()) {
         extendDatas = new ArrayList<>();
      }

      if (extendList != null && !extendList.isEmpty()) {
         extendList = new ArrayList<>();
      }
   }

   public CefDataExtHandler copy() throws CloneNotSupportedException {
      CefDataExtHandler rez = (CefDataExtHandler) clone();
      if (extendList != null) {
         rez.extendList = new ArrayList<>(extendList);
         rez.extendDatas = extendDatas.stream().map(item -> item.copy())
             .collect(Collectors.toList());
         for (int i = 0; i < extendList.size(); i++) {
            rez.onAddingExtend(rez.extendList.get(i), rez.extendDatas.get(i));
         }
      }
      return rez;
   }

   @Override
   protected Object clone() throws CloneNotSupportedException {
      CefDataExtHandler rez = (CefDataExtHandler) super.clone();
      rez.extendList = null;
      rez.extendDatas = null;
      return rez;
   }
}
